//
//  MultiSelectViewHelper.swift
//  MySwiftTool
//
//  Created by Chris on 2021/4/28.
//

import UIKit

class MultiSelectViewHelper: NSObject {

    enum AfterCompletionType {
        case hide,add
    }
    public typealias SelectRangeChangedBlock = (_ startIndex: Int, _ endIndex: Int, _ completed: Bool) -> ()

    public static let initialValue = 5201314
    var cellHeight: CGFloat = 50.0
    var startY: CGFloat = 0.0
    var endY: CGFloat = 0.0
    public var startIndex: Int {
        get {
            Int(startY) / Int(cellHeight)
        }

        set {
            startY = CGFloat(newValue) * cellHeight
        }
    }
    public var endIndex: Int = 5201314

    var srcBlock: SelectRangeChangedBlock?
    private var scrollView: UIScrollView?
    private var target: Any?
    private var afterCompletionType: AfterCompletionType?
    public var buttons: Array<TouchButton>?
    public func addRangeChangedListner(_ target: Any,
                                       _ afterCompletionType: AfterCompletionType,
                                       _ scrollView: UIScrollView,
                                       _ listner: @escaping SelectRangeChangedBlock) {

        self.target = target
        self.srcBlock = listner
        self.scrollView = scrollView
        self.afterCompletionType = afterCompletionType
    }

    private func addTopView() {
        let topView = MultiSelectTopView()
        topView.backgroundColor = .gray
        let maxValue = max(startIndex, endIndex)
        let minValue = min(startIndex, endIndex)
        topView.frame = CGRect.init(x: 0, y: CGFloat(minValue) * cellHeight, width: scrollView?.frame.width ?? 0, height: CGFloat(maxValue - minValue + 1) * cellHeight)
        scrollView?.addSubview(topView)
    }
}

extension MultiSelectViewHelper: TouchButtonPositionDelegate {

    /// 手指触摸的位置
    /// - Parameter position: 手指在scrollView上的坐标
    func positionCallBack(position: CGPoint) {
        checkIndex(y: position.y)
        srcBlock!(startIndex,endIndex,false)
    }


    /// 手指离开屏幕
    /// - Parameter sender: 手指最先按住的button
    func touchesEnded(sender: TouchButton) {
        buttons?.forEach({$0.isSelected = false})
        if endIndex == MultiSelectViewHelper.initialValue {
            startIndex = sender.tag
            endIndex = startIndex
        }
        srcBlock!(startIndex,endIndex,true)
        if afterCompletionType == .add {
            addTopView()
        }
        startY = 0
        endY = 0
        endIndex = MultiSelectViewHelper.initialValue
    }

    func startListenScrollView() {
        startAutoScrollTimer()
    }


    /// 根据获取到的y坐标进行处理
    /// - Parameter y: 手指相对scrollView的y坐标
    private func checkIndex(y: CGFloat) {
        let index: Int = Int(y) / Int(cellHeight)

        if index >= buttons!.count {
            return
        }
        let button: TouchButton = buttons![index]

        if startY == 0 {
            startY = y
        }
        endY = y
        if endIndex == MultiSelectViewHelper.initialValue {
            endIndex = index
        }

        // 手指在滑动的时候会频繁调用此方法，只有在手指当前index跟之前获取的不一致再进行处理避免多余的开销
        if index != endIndex {
            var inTheOutside = true
            // 检查当前选中的区域有没有和已经选中的区域有重合
            let selectRange = startY > y ? y...startY : startY...y
            for view: UIView in button.superview!.subviews where view.isKind(of: MultiSelectTopView.self){
                let sY = view.frame.origin.y
                let eY = view.frame.maxY
                let beforRange = sY...eY
                if selectRange.overlaps(beforRange) {
                    inTheOutside = false
                    break
                }
            }

            if inTheOutside == true {
                endIndex = index
            }
            // 有效区间内的button设置选中状态
            for b: TouchButton in buttons! {
                if b.tag < min(startIndex, endIndex) || b.tag > max(startIndex, endIndex) {
                    b.isSelected = false
                } else {
                    b.isSelected = true
                }
            }
        }
    }


    /// 检查手指是否移动到scrollView底部，如果在底部，让scrollView自动滚动
    @objc private func checkScrollViewAutoScroll() {
        let y = endY
        let offY = self.scrollView!.contentOffset.y
        let maxOffY = self.scrollView!.contentSize.height - self.scrollView!.frame.height
        if y > offY + self.scrollView!.frame.height - cellHeight * 2 {
            let newOffY = offY + cellHeight > maxOffY ? maxOffY : offY + cellHeight
            self.scrollView!.setContentOffset(CGPoint.init(x: self.scrollView!.contentOffset.x, y: newOffY), animated: true)
            endY += cellHeight
            checkIndex(y: endY)
        }
    }

    public func startAutoScrollTimer() {
        let timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(checkScrollViewAutoScroll), userInfo: nil, repeats: true)
        RunLoop.main.add(timer, forMode: .common)
    }

}
